package com.ssy.lingxi.member.merchant.handler.validator;

import com.ssy.lingxi.member.merchant.entity.CountryCodeDO;
import com.ssy.lingxi.member.merchant.handler.annotation.PhoneCheckClassAnnotation;
import com.ssy.lingxi.member.merchant.repository.CountryCodeRepository;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import javax.annotation.Resource;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 根据国家代码校验手机号码注解实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2020-12-04
 */
public class PhoneCheckClassValidator implements ConstraintValidator<PhoneCheckClassAnnotation, Object> {
    private static final SpelExpressionParser PARSER = new SpelExpressionParser();
    private String countryCodeFieldName;
    private String phoneFieldName;
    private String countryCode;
    private Boolean ignore;

    @Resource
    private CountryCodeRepository countryCodeRepository;

    @Override
    public void initialize(PhoneCheckClassAnnotation constraintAnnotation) {
        countryCodeFieldName = constraintAnnotation.countryCodeFieldName();
        phoneFieldName = constraintAnnotation.phoneFieldName();
        countryCode = constraintAnnotation.countryCode();
        ignore = constraintAnnotation.ignore();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        Object codeObj = PARSER.parseExpression(countryCodeFieldName).getValue(value);

        if(Objects.isNull(codeObj)) {
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate("国家代码不能为空").addConstraintViolation();
            return false;
        }

        Object phoneObj = PARSER.parseExpression(phoneFieldName).getValue(value);
        if(Objects.isNull(phoneObj)) {
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate("手机号码不能为空").addConstraintViolation();
            return false;
        }

        countryCode = String.valueOf(codeObj);
        String phoneNum = String.valueOf(phoneObj);

        List<CountryCodeDO> countryCodeDOList = countryCodeRepository.findAll();
        CountryCodeDO countryCodeDO = countryCodeDOList.stream().filter(cc -> cc.getCode().equals(countryCode)).findFirst().orElse(null);
        if(countryCodeDO == null) {
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate("国家代码不在系统定义范围内").addConstraintViolation();
            return false;
        }

        boolean isPhoneCorrect = true;
        String errMsg = "请输入正确的手机号码";
        final String localPhonePrefix = "+86";
        if (ignore){
            return true;
        }
        if(phoneNum.length() != countryCodeDO.getPhoneLength()) {
            if(!localPhonePrefix.equals(countryCodeDO.getCode())) {
                errMsg = "Phone number format is incorrect";
            }
            isPhoneCorrect = false;
        }

        if(!isPhoneCorrect) {
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(errMsg).addConstraintViolation();
            return false;
        }

        if (localPhonePrefix.equals(countryCode)) {
            String regex = "^(1[3-9]\\d{9}$)";
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(phoneNum);
            isPhoneCorrect = m.matches();
        }

        if(!isPhoneCorrect) {
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(errMsg).addConstraintViolation();
            return false;
        }

        return true;
    }
}
